#ifndef VECTOR_INC_H_
#define VECTOR_INC_H_

#ifndef CTL_VEC_MINIMAL_SIZE
#define CTL_VEC_MINIMAL_SIZE 8
#endif
#ifndef CTL_VEC_GROW_FACTOR
#define CTL_VEC_GROW_FACTOR 2
#endif
#ifndef CTL_VEC_TRIM_RATIO
#define CTL_VEC_TRIM_RATIO 0.5
#endif

#define DECL_VEC(TYPE) \
typedef struct { \
  TYPE *data; \
  size_t begin_idx; \
  size_t size; \
  size_t capacity; \
} ctl_vec_##TYPE; \
DECL_RES_P(ctl_vec_##TYPE); \
size_t ctl_vec_##TYPE##_size(ctl_vec_##TYPE* vec); \
size_t ctl_vec_##TYPE##_begin_idx(ctl_vec_##TYPE* vec); \
ctl_res_ctl_vec_##TYPE##_p ctl_vec_##TYPE##_new(size_t size); \
ctl_res_void ctl_vec_##TYPE##_free(ctl_vec_##TYPE *vec); \
ctl_res_void ctl_vec_##TYPE##_ctor_with_size(ctl_vec_##TYPE *vec, size_t size); \
ctl_res_void ctl_vec_##TYPE##_ctor(ctl_vec_##TYPE *vec); \
ctl_res_void ctl_vec_##TYPE##_dtor(ctl_vec_##TYPE *vec); \
ctl_res_void ctl_vec_##TYPE##_copy(ctl_vec_##TYPE *dst, const ctl_vec_##TYPE *src); \
ctl_res_void ctl_vec_##TYPE##_set_at(ctl_vec_##TYPE *vec, size_t index, const TYPE data); \
ctl_res_##TYPE ctl_vec_##TYPE##_get_at(ctl_vec_##TYPE *vec, size_t index); \
ctl_res_void ctl_vec_##TYPE##_push_back(ctl_vec_##TYPE *vec, const TYPE data); \
ctl_res_##TYPE ctl_vec_##TYPE##_pop_back(ctl_vec_##TYPE* vec); \
ctl_res_void ctl_vec_##TYPE##_trim(ctl_vec_##TYPE *vec);\
ctl_res_void ctl_vec_##TYPE##_insert_range(ctl_vec_##TYPE *vec, size_t insert_start_idx, \
                               size_t insert_count, \
                               const TYPE *data_arr); \
ctl_res_void ctl_vec_##TYPE##_insert_at(ctl_vec_##TYPE* vec, size_t insert_idx, const TYPE data); \
ctl_res_void ctl_vec_##TYPE##_remove_range(ctl_vec_##TYPE *vec, size_t remove_idx, size_t remove_count); \
ctl_res_void ctl_vec_##TYPE##_remove_at(ctl_vec_##TYPE *vec, size_t remove_idx); \
ctl_res_void ctl_vec_##TYPE##_push_front(ctl_vec_##TYPE *vec, const TYPE data); \
ctl_res_##TYPE ctl_vec_##TYPE##_pop_front(ctl_vec_##TYPE *vec); \
ctl_res_void ctl_vec_##TYPE##_reserve(ctl_vec_##TYPE* vec, size_t new_capacity); \
ctl_res_void ctl_vec_##TYPE##_resize(ctl_vec_##TYPE* vec, size_t new_capacity); 
#endif